const axios = require('axios')
const WXBizDataCrypt = require('./WXBizDataCrypt')
const mpApiUrl = require('./api-url').miniProgram
const utils = require('./utils')
const cache = require('memory-cache')

class MiniProgram {
  constructor(config = {}) {
    this.config = config
    this.axios = this.createAxios()
  }

  createAxios(config = {}) {
    const instance = axios.create({})

    instance.interceptors.request.use(
      (config) => {
        config.onSuccess = (res) => {
          return Promise.resolve(res)
        }

        config.onFail = (error, res) => {
          return Promise.reject([error, res])
        }

        if (config.debug) console.log(config)

        return config
      },
      (error) => {
        return Promise.reject([error])
      }
    )

    instance.interceptors.response.use(
      (response) => {
        const { config } = response

        const { status, data } = response

        if (status && status == 200) {
          if (data.errcode) {
            return config.onFail(data.errmsg, data)
          } else {
            return config.onSuccess(data)
          }
        } else {
          console.log('status', status)
          return config.onFail('数据解析异常', data)
        }
      },
      (error) => {
        const { config, response } = error

        if (response) {
          return config.onFail('服务器异常', response.data)
        } else {
          if (config) {
            return config.onFail(error.message, error)
          } else {
            return Promise.reject([error])
          }
        }
      }
    )

    return instance
  }

  /**
   * 登录凭证校验
   * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
   *
   * @param {*} options.js_code  登录时获取的 code
   * @param {*} [options.appId]  小程序appId
   * @param {*} [options.secret] 小程序secret
   */
  async code2Session(options = {}) {
    options = {
      appid: options.appId || this.config.appId,
      secret: options.secret || this.config.secret,
      grant_type: 'authorization_code',
      ...options,
    }

    utils.ajv(options, {
      required: ['appid', 'secret', 'js_code', 'grant_type'],
    })

    return this.axios(mpApiUrl.code2Session, {
      params: options,
    })
  }

  /**
   * 解密数据
   * https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html#加密数据解密算法
   *
   * @param {String} sessionKey sessionKey(使用code2Session换取)
   * @param {String} encryptedData 包括敏感数据在内的完整用户信息的加密数据
   * @param {String} iv 加密算法的初始向量
   * @param {String} [options.appId]  小程序appid
   */
  async decryptData(options = {}) {
    options = {
      appId: options.appId || this.config.appId,
      ...options,
    }

    const { appId, sessionKey, encryptedData, iv } = options

    var pc = new WXBizDataCrypt(appId, sessionKey)

    return pc.decryptData(encryptedData, iv)
  }

  /**
   * 获取小程序码(数量暂无限制)
   * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html
   *
   * @param {String} scene 场景
   * @param {String} [page] 主页
   * @param {String} [envVersion] 要打开的小程序版本
   * @param {String} [accessAoken] 接口调用凭据
   */
  async getUnlimited(options = {}) {
    const envVersion = options.envVersion || this.config.envVersion

    return this.axios('https://api.weixin.qq.com/wxa/getwxacodeunlimit', {
      method: 'post',
      params: {
        access_token: options.accessAoken,
      },
      data: {
        scene: options.scene,
        page: options.page,
        env_version: envVersion,
      },
      responseType: 'arraybuffer',
    })
  }

  /**
   * 获取小程序全局唯一后台接口调用凭据（access_token）
   * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html
   *
   * @param {String} [appId] 小程序唯一凭证
   * @param {String} [secret] 小程序唯一凭证密钥
   */
  async getAccessToken(options = {}) {
    const appId = options.appId || this.config.appId
    const secret = options.secret || this.config.secret

    return this.axios('https://api.weixin.qq.com/cgi-bin/token', {
      params: {
        grant_type: 'client_credential',
        appid: appId,
        secret,
      },
    })

    // const cacheTokenName = 'wechat_access_token_' + appId
    // const accessAoken = cache.get(cacheTokenName)

    // // 获取缓存
    // if (accessAoken) {
    //   console.log('获取缓存accessAoken')
    //   return accessAoken
    // } else {
    //   return this.axios('https://api.weixin.qq.com/cgi-bin/token', {
    //     params: {
    //       grant_type: 'client_credential',
    //       appid: appId,
    //       secret,
    //     },
    //   }).then((res) => {
    //     cache.put(cacheTokenName, res.access_token, res.expires_in * 1000)
    //     if (this.config.accessTokenRefresh) this.config.accessTokenRefresh(res)

    //     return res.access_token
    //   })
    // }
  }

  /**
   * 发送订阅消息
   * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
   *
   * @param {String} [appId] 小程序唯一凭证
   * @param {String} [secret] 小程序唯一凭证密钥
   */
  async send(options = {}) {
    const accessAoken =
      options.accessAoken ||
      (await this.getAccessToken({
        appId: options.appId,
        secret: options.secret,
      }))

    return this.axios(`https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=${accessAoken}`, {
      method: 'post',
      data: {
        // access_token: accessAoken,
        touser: options.touser,
        template_id: options.template_id,
        page: options.page,
        data: options.data,
      },
      debug: true,
    })
  }
}

module.exports = MiniProgram
